﻿define(function (require, exports, module) {
    var CPDF_TextObject = require('./Reader_TextObject.js');
    var CPDF_Point = FXREADER.CPDF_Point;
    var CPDF_Rect = FXREADER.CPDF_Rect;
    var CommonTools = FXREADER.Common;

    var BOUND_INFO = function (nStartIndex, nEndIndex) {
        this.start_index = nStartIndex;
        this.end_index = nEndIndex;
    };
    FXREADER.PDFData.Text.BOUND_INFO = BOUND_INFO;
    var CHAR_INFO = FXREADER.PDFData.Text.CharInfo;

    FXREADER.PDFData.Text.CPDF_TextPage = function () {
        this.textObjectList = [];       //Text object array
        this.nStrSize = 0;      // the total number of characters in page
        this.nPageIndex = -1;
        this.nlineSize = 0; //TextPage_LineSize();
        var _self = this;
        function _TextPage_LineSize() {
            var objSize = _self.textObjectList.length;
            if (objSize == 0) {
                return 0;
            }
            return _self.textObjectList[objSize - 1].nLineIndex + 1;
        }

        this.Init = function (jsonData) {
            try {
                if (jsonData == null)
                    return false;
                if (jsonData.pagenum != null) {
                    this.nPageIndex = parseInt(jsonData.pagenum);
                }
                else
                    return false;
                if (jsonData.texts != null) {
                    var textObjArr = jsonData.texts;
                    for (var i = 0; i < textObjArr.length; i++) {
                        var textObj = textObjArr[i];
                        if (textObj.li == null || textObj.ci == null || textObj.oi == null || textObj.cs == null)
                            return false;
                        var fxTxtObj = new CPDF_TextObject();
                        fxTxtObj.nLineIndex = parseInt(textObj.li);
                        fxTxtObj.nObjIndex = parseInt(textObj.oi);
                        fxTxtObj.nCharIndex = parseInt(textObj.ci);
                        var charsArr = textObj.cs;
                        for (var j = 0; j < charsArr.length; j++) {
                            var charObj = charsArr[j];
                            if (charObj.length != 5)
                                return false;
                            var charInfo = new CHAR_INFO();
                            var left = parseFloat(charObj[0]),
                                  top = parseFloat(charObj[1]),
                                  width = parseFloat(charObj[2]),
                                  height = parseFloat(charObj[3]);
                            charInfo.fCharRect = new CPDF_Rect(left, top, left + width, top + height);
                            FXREADER.RectUtils.Normalize(charInfo.fCharRect);
                            charInfo.charCode = parseInt(charObj[4]);
                            fxTxtObj.charInfoArray.push(charInfo);
                        }
                        fxTxtObj.Init();
                        this.textObjectList.push(fxTxtObj);
                    }
                    var lastObj = this.textObjectList[this.textObjectList.length - 1];
                    this.nStrSize = lastObj.nCharIndex + lastObj.GetStrSize() + 1;
                    this.nlineSize = _TextPage_LineSize();
                }
                else {
                    return false;
                }
            }
            catch (ex) {
                return false;
            }
            return true;
        };

        this.GetObjTextIndexByPoint = function (pdfPt) {
            var size = this.textObjectList.length;
            for (var i = 0; i < size; i++) {
                var rect = this.textObjectList[i].GetAllObjectPDFRect(false);
                if (FXREADER.RectUtils.PtInRect(rect,pdfPt.x, pdfPt.y)) {
                    //var text = this.textObjectList[i].GetAllCharCodeText(); //测试
                    return i;
                }
            }
            return -1;
        };

        this.GetIndexByPoint = function (pdfPt) //Get char index (relative to the entire page)
        {
            var size = this.textObjectList.length;
            var obj_index = -1;
            obj_index = this.GetObjTextIndexByPoint(pdfPt);
            if (obj_index == -1) {
                return -1;
            }
            var char_count = this.textObjectList[obj_index].GetSize();
            var index = -1;
            for (var j = 0; j < char_count; j++) {
                var rect = this.textObjectList[obj_index].GetObjectPDFRect(j, 1);
                if (FXREADER.RectUtils.PtInRect(rect,pdfPt.x, pdfPt.y)) {
                    index = j;
                    break;
                }
            }
            if (index == -1) {
                return -1;
            }
            return this.textObjectList[obj_index].nObjIndex + index;
        };


        function _IsWordInfo  (ch) {
            //数字、字母；
            var regexp = /^[0-9a-zA-Z]*$/;
            if (ch > 255 || (!regexp.test(ch) && ch != '.' && ch != '-')) {
                return false;
            }
            return true;
        }


        this.GetPDFRect = function (obj_index, count) {
            var rect_array = [];
            var largeSize = this.GetSize();
            if (obj_index < 0 || obj_index >= largeSize || count <= 0)
                return rect_array;
            if (obj_index + count > largeSize) {
                count = largeSize - obj_index;
            }
            var start_index = obj_index;
            var start_listIndex = -1;
            var obj_startIndex = -1;
            var objSize = this.textObjectList.length;
            for (var i = 0; i < objSize; i++) {
                var textObj = this.textObjectList[i];
                var endindex = textObj.nObjIndex + textObj.GetSize() - 1;
                if (start_index <= endindex) {
                    start_listIndex = i;
                    obj_startIndex = start_index - textObj.nObjIndex;
                    if (obj_startIndex < 0) {
                        obj_startIndex = 0;
                        count--;
                    }
                    break;
                }
            }
            var next_index = start_listIndex;
            var objText_index = obj_startIndex;
            var numbers = 0;
            while (count > 0) {
                if (next_index >= objSize)
                    return 0;
                var next_textObj = this.textObjectList[next_index];
                var size = next_textObj.GetSize();
                var nLeaveCount = size - objText_index;
                var rect = next_textObj.GetObjectPDFRect(objText_index, count);
                rect_array.push(rect);
                numbers++;
                count = count - nLeaveCount;
                if (count > 0 && next_index < objSize - 1) {
                    var end_index = next_textObj.nObjIndex + size - 1;
                    var next_start = this.textObjectList[next_index + 1].nObjIndex;
                    if (next_start - end_index != 1) //TextObj与TextObj空格【间隔】
                    {
                        count--;
                    }
                }
                next_index++;
                objText_index = 0;
            }
            return rect_array; //numbers;
        };


        this.GetIndexByCharIndex = function (char_index) //通过char_index获取obj_index
        {
            if (char_index >= this.nStrSize)
                return -1;
            var size = this.textObjectList.length;

            for (var i = 0; i < size; i++) {
                var textObj = this.textObjectList[i];
                if (char_index <= textObj.nCharIndex + textObj.GetStrSize() - 1) {
                    if (char_index < textObj.nCharIndex) {
                        if (i > 0 && textObj.nLineIndex != this.textObjectList[i - 1].nLineIndex) {
                            return textObj.nObjIndex;
                        }
                        else {
                            return textObj.nObjIndex - 1;
                        }
                    }
                    var index = char_index - textObj.nCharIndex;
                    return textObj.nObjIndex + textObj.GetOBjectIndex(index);
                }
            }
            return 0;
        };

        this.GetStrSize = function () {
            return this.nStrSize;
        };


        this.GetSize = function () //获取所有字符数
        {
            var size = this.textObjectList.length;
            if (size == 0) {
                return 0;
            }
            else {
                return this.textObjectList[size - 1].nObjIndex + this.textObjectList[size - 1].GetSize();
            }
        };

        this.GetPageAllText = function ()   //GetPageText
        {
            var objSize = this.textObjectList.length;
            if (objSize == 0) {
                return "";
            }
            return this.GetPageText(0, this.GetSize());
        };

        this.GetPageText = function (obj_index, count) //obj_index --> char_index  count-->char_count
        {
            var largeSize = this.GetSize();  //获取所有字符数
            if (obj_index < 0 || obj_index >= largeSize || count <= 0)
                return "";
            if (obj_index + count > largeSize) {
                count = largeSize - obj_index;
            }
            var start_index = obj_index;
            var start_listIndex = -1; //文本对象索引
            var obj_startIndex = -1;  //起始字符索引
            var objSize = this.textObjectList.length; //文本对象数量
            var csText = "";
            for (var i = 0; i < objSize; i++) {
                var textObj = this.textObjectList[i];
                var endindex = textObj.nObjIndex + textObj.GetSize() - 1;
                if (start_index <= endindex) {
                    start_listIndex = i;
                    obj_startIndex = start_index - textObj.nObjIndex;
                    if (obj_startIndex < 0) {
                        obj_startIndex = 0;
                        csText = " "; //单词前加个空格
                        count--;
                    }
                    break;
                }
            }
            var next_index = start_listIndex;
            var objText_index = obj_startIndex;
            while (count > 0) {
                if (next_index >= objSize)
                    return "";
                var next_textObj = this.textObjectList[next_index];
                var size = next_textObj.GetSize(); //当前文本对象的字符数量
                var nLeaveCount = size - objText_index;
                csText += next_textObj.GetCharCodeText(objText_index, count);
                count = count - nLeaveCount;
                if (count > 0 && next_index != objSize - 1) {
                    var next2_textObj = this.textObjectList[next_index + 1];
                    var next_start = next2_textObj.nObjIndex;
                    var next_line = next2_textObj.nLineIndex;

                    var nLine = next_textObj.nLineIndex;
                    var nEnd = next_textObj.nObjIndex + next_textObj.GetSize() - 1;
                    if (next_line != nLine) {
                        var next_charStart = next2_textObj.nCharIndex;
                        var cur_charEnd = next_textObj.nCharIndex + next_textObj.GetStrSize() - 1;
                        if (next_charStart - cur_charEnd != 1) {
                            csText += "\r\n";
                        }
                    }
                    else if (next_start - nEnd != 1) {
                        csText += " ";
                        count--;
                    }
                }
                next_index++;
                objText_index = 0;
            }
            return csText;
        }


        function _GetBoundPageInfo(rcBound, nfrom, nto, boundInfo) {
            if (nfrom > nto) {
                return false;
            }
            var nStart = -1;
            var nEnd = -1;
            var i;
            for (i = nfrom; i <= nto; i++) {
                var rect = _self.textObjectList[i].GetAllObjectPDFRect();
                FXREADER.RectUtils.Intersect(rect,rcBound);
                if (!FXREADER.RectUtils.IsEmpty(rect)) {
                    var size = _self.textObjectList[i].GetSize();
                    for (var j = 0; j < size; j++) {
                        var rect = _self.textObjectList[i].GetObjectPDFRect(j, 1);
                        FXREADER.RectUtils.Intersect(rect,rcBound);
                        if (!FXREADER.RectUtils.IsEmpty(rect)) {
                            nStart = _self.textObjectList[i].nObjIndex + j;
                            break;
                        }
                    }
                }
                if (nStart != -1) {
                    break;
                }
            }
            if (nStart == -1) {
                return false;
            }
            for (i = nto; i >= nfrom; i--) {
                var rect = _self.textObjectList[i].GetAllObjectPDFRect();
                FXREADER.RectUtils.Intersect(rect,rcBound);
                if (!FXREADER.RectUtils.IsEmpty(rect)) {
                    var size = _self.textObjectList[i].GetSize();
                    for (var j = size - 1; j >= 0; j--) {
                        var rect = _self.textObjectList[i].GetObjectPDFRect(j, 1);
                        FXREADER.RectUtils.Intersect(rect,rcBound);
                        if (!FXREADER.RectUtils.IsEmpty(rect)) {
                            nEnd = _self.textObjectList[i].nObjIndex + j;
                            break;
                        }
                    }
                }
                if (nEnd != -1) {
                    break;
                }
            }
            boundInfo.start_index = nStart;
            boundInfo.end_index = nEnd;
            return true;

        }

        this.GetBoundPageInfo = function (rcBound, bound_array) {
            var nCount = this.textObjectList.length;
            var nstart = -1;
            var nEnd = -1;

            for (var i = 0; i < this.nlineSize; i++) {
                var start_index = -1;
                var end_index = -2;
                var lineRangeInfo = new BOUND_INFO(-1, -2);
                this.GetLineRange(i, lineRangeInfo);
                var info = new BOUND_INFO(-1, -1); ;
                if (_GetBoundPageInfo(rcBound, lineRangeInfo.start_index, lineRangeInfo.end_index, info)) {
                    bound_array.push(info);
                }
            }
            if (bound_array.length == 0) {
                return false;
            }
            return true;
        }

        function _GetWordLeftPos(obj_index)
        {
	        if(obj_index<0 || obj_index>=_self.GetSize())
	        {
		        return -1;
	        }
		    var csText = _self.GetPageText(obj_index, 1);
	        var  size = csText.length;
	        if (size == 0 )
	        {
		        return obj_index;
	        }
	        var j = -1;
	        for(j=size-1;j>=0;j--)
	        {
		        if( !_IsWordInfo( csText.charAt(j) )  )
		        {
			        if (j==size-1)
			        {
				        return -1;
			        }
			        else
			        {
				        return obj_index;
			        }
		        }
	        }

            var nWord_Line = _self.GetLineIndexByIndex(obj_index);
            var lineRangeInfo = new BOUND_INFO(-1, -1);
            var bRet = _self.GetLineRange(nWord_Line, lineRangeInfo);
	        if(!bRet)
                return -1;
            var  line_stIndex = lineRangeInfo.start_index;
            var  line_endIndex = lineRangeInfo.end_index;
            line_stIndex = _self.textObjectList[line_stIndex].nObjIndex;
	        line_endIndex = _self.textObjectList[line_endIndex].nObjIndex + _self.textObjectList[line_endIndex].GetSize() - 1;
	        var bStart = false;

	        var start_index=0;
	        for (j=obj_index-1; j>=line_stIndex; j--)
	        {
	            csText = _self.GetPageText(j, 1);
		        var  size = csText.length;
		        var line_index = _self.GetLineIndexByIndex(j);
		        for(var i=size-1; i>=0; i--)
		        {
			        if(!_IsWordInfo(csText.charAt(i))  )
			        {
				        if (i == size-1)
				        {
					        start_index = j+1;
				        }
				        else
				        {
					        start_index = j;
				        }
				        bStart = true;
				        break;
			        }
		        }
		        if (bStart == true)
		        {
			        break;
		        }
	        }
	        if (!bStart)
	        {
		        start_index =line_stIndex;
	        }

	        if (start_index != line_stIndex)
	        {
		        return start_index;
	        }
	        if (nWord_Line == 0)
	        {
		        return start_index;
	        }

            lineRangeInfo.start_index = -1;
            lineRangeInfo.end_index = -1;
            bRet = _self.GetLineRange(nWord_Line - 1, lineRangeInfo);
            if(!bRet)
                return -1;
            line_stIndex = lineRangeInfo.start_index;
            line_endIndex = lineRangeInfo.end_index;
            line_stIndex = _self.textObjectList[line_stIndex].nObjIndex;
            line_endIndex = _self.textObjectList[line_endIndex].nObjIndex + _self.textObjectList[line_endIndex].GetSize() - 1;
            csText = _self.GetPageText(line_endIndex, 1);
	        size = csText.length;
	        var temp_text = "";
	        temp_text = _self.GetPageText(start_index, 1);
	        if (temp_text.charAt(0)!= '-' && csText.charAt(size-1) != '-')
	        {
		        return start_index;
	        }
	        var temp_pos= _GetWordLeftPos(line_endIndex);
	        if( temp_pos != -1)
	        {
		        start_index = temp_pos;
	        }
	        return start_index;
        }

        function _GetWordRightPos( obj_index)
        {
            if (obj_index < 0 || obj_index >= _self.GetSize())
	        {
		        return -1;
	        }
		    var csText = _self.GetPageText(obj_index, 1);
	        var size=csText.length;
	        if (size == 0 )
	        {
		        return obj_index;
	        }
	        var j = -1;
	        for(j=0; j<size; j++)
	        {
		        if( !_IsWordInfo(csText.charAt(j)) )
		        {
			        if (j==0)
			        {
				        return -1;
			        }
			        else
			        {
				        return obj_index;
			        }
		        }
	        }


            var nWord_Line = _self.GetLineIndexByIndex(obj_index);
            var lineRangeInfo = new BOUND_INFO(-1, -1);
            var bRet = _self.GetLineRange(nWord_Line, lineRangeInfo);
	        if(!bRet)
                return -1;
            var  line_stIndex = lineRangeInfo.start_index;
            var  line_endIndex = lineRangeInfo.end_index;

            line_stIndex = _self.textObjectList[line_stIndex].nObjIndex;
            line_endIndex = _self.textObjectList[line_endIndex].nObjIndex + _self.textObjectList[line_endIndex].GetSize() - 1;
	        var bEnd=false;
	
	
	        var end_index=0;
	        for (j=obj_index+1; j<=line_endIndex; j++)
	        {
	            csText = _self.GetPageText(j, 1);
		        var size = csText.length;
		        for(var i=0;i<size;i++)
		        {
			        if(!_IsWordInfo(csText.charAt(i)) )//255以上是非abc字符
			        {
				        if (i==0)
				        {
					        end_index=j-1;
				        }
				        else
				        {
					        end_index=j;
				        }
				        bEnd = true;
				        break;
			        }
		        }
		        if (bEnd == true)
		        {
			        break;
		        }
	        }
	        if (!bEnd)
	        {
		        end_index =line_endIndex;
	        }
	
	        if (end_index != line_endIndex)
	        {
		        return end_index;
	        }

		    if (nWord_Line == _self.nlineSize - 1)
	        {
		        return end_index;
	        }

            lineRangeInfo.start_index = -1;
            lineRangeInfo.end_index = -1;
            bRet = _self.GetLineRange(nWord_Line + 1, lineRangeInfo);
            if(!bRet)
                return -1;
            line_stIndex = lineRangeInfo.start_index;
            line_endIndex = lineRangeInfo.end_index;
            line_stIndex = _self.textObjectList[line_stIndex].nObjIndex;
            line_endIndex = _self.textObjectList[line_endIndex].nObjIndex + _self.textObjectList[line_endIndex].GetSize() - 1;
            csText = _self.GetPageText(line_endIndex, 1);
	        var temp_text = "";
	        temp_text = _self.GetPageText(end_index, 1);
	        if (temp_text.charAt(temp_text.length-1)!='-' && csText.charAt(0)!= '-')
	        {
		        return end_index;
	        }
	        var temp_pos= _GetWordRightPos(line_stIndex);
	        if( temp_pos != -1)
	        {
		        end_index = temp_pos;
	        }
	        return end_index;
        }


        this.GetWordRange = function(obj_index,boundInfo)
        {
	        if(obj_index<0 || obj_index>=this.GetSize())
	        {
		        return false;
	        }

	        boundInfo.start_index = _GetWordLeftPos(obj_index);
	        if (boundInfo.start_index == -1)
	        {
		        boundInfo.start_index = boundInfo.end_index = obj_index;
	        }
	        boundInfo.end_index = _GetWordRightPos(obj_index);
	        if (boundInfo.end_index == -1)
	        {
		        boundInfo.start_index = boundInfo.end_index = obj_index;
	        }
	        return true;
        };

        this.GetLineRange = function (line_index, boundInfo) {
            var index = this.BinSearch(line_index);
            if (index == -1) {
                return false;
            }
            boundInfo.start_index = boundInfo.end_index = index;
            for (var i = index - 1; i >= 0; i--) {
                if (this.textObjectList[i].nLineIndex == line_index) {
                    boundInfo.start_index = i;
                }
                else {
                    break;
                }
            }
            var size = this.textObjectList.length;
            for (var j = index + 1; j < size; j++) {
                if (this.textObjectList[j].nLineIndex == line_index) {
                    boundInfo.end_index = j;
                }
                else {
                    break;
                }
            }
            return true;
        };

        this.BinSearch = function (line_index) {
            //在有序表R[0..n-1]中进行二分查找，成功时返回结点的位置，失败时返回零;
            var low = 0, high = this.textObjectList.length - 1, mid; //置当前查找区间上、下界的初值;
            while (low <= high) {
                //当前查找区间R[low..high]非空
                mid = parseInt((low + high) / 2);
                if (this.textObjectList[mid].nLineIndex == line_index) return mid; //查找成功返回;
                else if (this.textObjectList[mid].nLineIndex > line_index)
                    high = mid - 1; //继续在R[low..mid-1]中查找;
                else
                    low = mid + 1; //继续在R[mid+1..high]中查找;
            }
            return -1; //当low>high时表示查找区间为空，查找失败;
        };

        this.GetLineIndexByIndex = function (obj_index) {
            var size = this.textObjectList.length;
            for (var i = 0; i < size; i++) {
                if (obj_index <= this.textObjectList[i].nObjIndex + this.textObjectList[i].GetSize() - 1) {
                    return this.textObjectList[i].nLineIndex;

                }
            }
            return -1;
        };
        /*
        this.GetPDFRectPointInfo = function(obj_index,count,rcPoint_array)
        {
        var  largeSize = this.GetSize();
        if(obj_index<0 || obj_index>=largeSize || count<=0)
        return;

        if (obj_index+count > largeSize)
        {
        count = largeSize-obj_index;
        }
        var start_index = obj_index;
        var start_listIndex = -1;
        var obj_startIndex=-1;
        var objSize = this.textObjectList.length;
        for (var i=0; i<objSize; i++)
        {
        var endindex = this.textObjectList[i].nObjIndex+this.textObjectList[i].GetSize()-1;
        if(start_index <= endindex)
        {
        start_listIndex = i;
        obj_startIndex = start_index-this.textObjectList[i].nObjIndex;
        if (obj_startIndex<0)
        {
        obj_startIndex=0;
        count--;
        }
        break;
        }
        }
        var next_index=start_listIndex;
        var objText_index=obj_startIndex;
        var numbers=0;
        while (count > 0)
        {
        if(next_index >= objSize)
        return;
        var size = this.textObjectList[next_index].GetSize();
        var nLeaveCount = size-objText_index;
        RECTPOINTINFO rcPoint=m_pTextObjectList[next_index].pTextObject->GetObjectPDFPointInfo(objText_index,count);
        rcPoint_array.Add(rcPoint);
        numbers++;
        count=count-nLeaveCount;
        if (count>0 && next_index<objSize-1)
        {
        int end_index = m_pTextObjectList[next_index].obj_index+size-1;
        int next_start= m_pTextObjectList[next_index+1].obj_index;
        if (next_start-end_index != 1) //TextObj与TextObj空格【间隔】
        {
        count--;
        }
        }
        next_index++;
        objText_index=0;	
        }
        return numbers;
        }
        */


        function _GetObjTextIndexByItemIndex(obj_index) {
            var size = _self.textObjectList.length;
            for (var i = 0; i < size; i++) {
                if (obj_index <= _self.textObjectList[i].nObjIndex + _self.textObjectList[i].GetSize() - 1) {
                    if (obj_index < _self.textObjectList[i].nObjIndex) {
                        return -1;
                    }

                    return i;
                }
            }
            return -1;
        }

        this.GetCaretByIndex = function (obj_index, caret_info, bLeft) {
            if (obj_index < 0 || obj_index >= this.GetSize()) {
                return false;
            }
            var objtext_index = _GetObjTextIndexByItemIndex(obj_index);
            if (objtext_index == -1) {
                return false;
            }
            var objText_index = obj_index - this.textObjectList[objtext_index].nObjIndex;
            this.textObjectList[objtext_index].GetTextCaretInfoByIndex(objText_index, caret_info, bLeft);
            caret_info.index += this.textObjectList[objtext_index].nObjIndex;

            return true;
        }

        this.GetCaretAtPoint = function (point, caret_info) {
            var objtext_index = this.GetObjTextIndexByPoint(point);
            if (objtext_index == -1) {
                return false;
            }
            var bRet = this.textObjectList[objtext_index].GetTextCaretInfo(point, caret_info);
            if (bRet) {
                caret_info.index += this.textObjectList[objtext_index].nObjIndex;
                return true;
            }
            else {
                return false;
            }
        }
    }

    return FXREADER.PDFData.Text.CPDF_TextPage;
});